/*
 */
package com.twp.auth.security;

import com.twp.auth.domain.authority.RequestUrl;
import com.twp.auth.domain.authority.Role;
import com.twp.auth.service.RequestUrlService;
import com.twp.auth.tuple.RequestUrlDetail;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;


/**
 * 访问决策
 *
 * @since JDK 1.8
 */
public class MyAccessDecisionManager implements AccessDecisionManager {
    private RequestUrlService requestUrlService;

    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {
        if (authentication == null) {
            throw new AccessDeniedException("无认证信息");
        }
        //放行app的请求
        if (authentication instanceof OAuth2Authentication) {
            OAuth2Authentication oauth = (OAuth2Authentication) authentication;
            LinkedHashMap map = (LinkedHashMap) oauth.getUserAuthentication().getDetails();

            if (map!=null&&map.containsKey("scope")&&"app".equals(String.valueOf(map.get("scope")))) {
                return;
            }
        }

        FilterInvocation fi = (FilterInvocation) object;
        //取当前url对应的角色列表
        List<RequestUrl> list = requestUrlService.selectAllRequestUrlForRole();

        for (RequestUrl url : list) {
            RequestMatcher requestMatcher = new AntPathRequestMatcher(url.getUrl(), url.getMethod());
            if (requestMatcher.matches(fi.getHttpRequest())) {
                //URL匹配成功
                //判断用户与URL中的角色是否匹配
                boolean matcher = false;
                for (Role role : url.getRoleList()) {
                    for (GrantedAuthority g : authentication.getAuthorities()) {
                        if (role.getRoleName().equals(g.getAuthority())) {
                            return;
                        }
                    }
                }
                if (matcher == false) {
                    throw new AccessDeniedException("请求未授权");
                }

            } else {
                //URL匹配不成功，不处理，允许通过
            }
        }

        return;
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }

    public RequestUrlService getRequestUrlService() {
        return requestUrlService;
    }

    public void setRequestUrlService(RequestUrlService requestUrlService) {
        this.requestUrlService = requestUrlService;
    }

}
